package com.jcark.utilscode.ext

import android.animation.Animator
import android.animation.IntEvaluator
import android.animation.ValueAnimator
import android.app.Activity
import android.content.ContextWrapper
import android.content.res.ColorStateList
import android.graphics.*
import android.graphics.drawable.BitmapDrawable
import android.view.View
import android.view.ViewGroup
import android.view.animation.AccelerateDecelerateInterpolator
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.core.content.ContextCompat

/**
 * 设置view显示
 */
fun View.visible() {
    visibility = View.VISIBLE
}

/**
 * 设置view占位隐藏
 */
fun View.invisible() {
    visibility = View.INVISIBLE
}

/**
 * 根据条件设置view显示隐藏 为true 显示，为false 隐藏
 */
fun View.visibleOrGone(flag: Boolean) {
    visibility = if (flag) {
        View.VISIBLE
    } else {
        View.GONE
    }
}

/**
 * 根据条件设置view显示隐藏 为true 显示，为false 隐藏
 */
fun View.visibleOrInvisible(flag: Boolean) {
    visibility = if (flag) {
        View.VISIBLE
    } else {
        View.INVISIBLE
    }
}

/**
 * 设置view隐藏
 */
fun View.gone() {
    visibility = View.GONE
}

/**
 * 将view转为bitmap
 */
@Deprecated("use View.drawToBitmap()")
fun View.toBitmap(scale: Float = 1f, config: Bitmap.Config = Bitmap.Config.ARGB_8888): Bitmap? {
    if (this is ImageView) {
        if (drawable is BitmapDrawable) return (drawable as BitmapDrawable).bitmap
    }
    this.clearFocus()
    val bitmap = createBitmapSafely(
        (width * scale).toInt(),
        (height * scale).toInt(),
        config,
        1
    )
    if (bitmap != null) {
        Canvas().run {
            setBitmap(bitmap)
            save()
            drawColor(Color.WHITE)
            scale(scale, scale)
            this@toBitmap.draw(this)
            restore()
            setBitmap(null)
        }
    }
    return bitmap
}

fun createBitmapSafely(width: Int, height: Int, config: Bitmap.Config, retryCount: Int): Bitmap? {
    try {
        return Bitmap.createBitmap(width, height, config)
    } catch (e: OutOfMemoryError) {
        e.printStackTrace()
        if (retryCount > 0) {
            System.gc()
            return createBitmapSafely(width, height, config, retryCount - 1)
        }
        return null
    }
}


fun Any?.notNull(notNullAction: (value: Any) -> Unit, nullAction1: () -> Unit) {
    if (this != null) {
        notNullAction.invoke(this)
    } else {
        nullAction1.invoke()
    }
}

/**
 * 判断当前view是否在屏幕可见
 */
fun View.getViewVisibleInWindow(activity: Activity, view: View, offsetY: Int): Boolean {
    val p = Point()
    activity.windowManager.defaultDisplay.getSize(p)
    val screenWidth: Int = p.x
    val screenHeight: Int = p.y
    val rect = Rect(0, 0, screenWidth, screenHeight) //得到屏幕矩阵
    val location = IntArray(2)
    location[1] = location[1] + offsetY
    view.getLocationInWindow(location)
    view.tag = location[1] //存储y方向的位置
    return view.getLocalVisibleRect(rect)
}

/**
 * 设置View的高度
 */
fun View.height(height: Int): View {
    val params = layoutParams ?: ViewGroup.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.WRAP_CONTENT
    )
    params.height = height
    layoutParams = params
    return this
}

/**
 * 设置View的宽度
 */
fun View.width(width: Int): View {
    val params = layoutParams ?: ViewGroup.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.WRAP_CONTENT
    )
    params.width = width
    layoutParams = params
    return this
}

/**
 * 设置View的宽度和高度
 * @param width 要设置的宽度
 * @param height 要设置的高度
 */
fun View.setSize(width: Int, height: Int): View {
    val params = layoutParams ?: ViewGroup.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.WRAP_CONTENT
    )
    params.width = width
    params.height = height
    layoutParams = params
    return this
}

/**
 * 触摸点是否在视图内
 * @param x x坐标
 * @param y y坐标
 */
fun View.isTouchPointInView(x: Int, y: Int): Boolean {
    val location = IntArray(2)
    getLocationOnScreen(location)
    val left = location[0]
    val top = location[1]
    val right = left + measuredWidth
    val bottom = top + measuredHeight
    return y in top..bottom && x >= left && x <= right
}

/**
 * 设置宽度，带有过渡动画
 * @param targetValue 目标宽度
 * @param duration 时长
 * @param action 可选行为
 * @return 动画
 */
fun View.animateWidth(
    targetValue: Int, duration: Long = 400, listener: Animator.AnimatorListener? = null,
    action: ((Float) -> Unit)? = null
): ValueAnimator? {
    var animator: ValueAnimator? = null
    post {
        animator = ValueAnimator.ofInt(width, targetValue).apply {
            addUpdateListener {
                width(it.animatedValue as Int)
                action?.invoke((it.animatedFraction))
            }
            if (listener != null) addListener(listener)
            setDuration(duration)
            start()
        }
    }
    return animator
}

/**
 * 设置高度，带有过渡动画
 * @param targetValue 目标高度
 * @param duration 时长
 * @param action 可选行为
 * @return 动画
 */
fun View.animateHeight(
    targetValue: Int,
    duration: Long = 400,
    listener: Animator.AnimatorListener? = null,
    action: ((Float) -> Unit)? = null
): ValueAnimator? {
    var animator: ValueAnimator? = null
    post {
        animator = ValueAnimator.ofInt(height, targetValue).apply {
            addUpdateListener {
                height(it.animatedValue as Int)
                action?.invoke((it.animatedFraction))
            }
            if (listener != null) addListener(listener)
            setDuration(duration)
            start()
        }
    }
    return animator
}

/**
 * 设置宽度和高度，带有过渡动画
 * @param targetWidth 目标宽度
 * @param targetHeight 目标高度
 * @param duration 时长
 * @param action 可选行为
 * @return 动画
 */
fun View.animateWidthAndHeight(
    targetWidth: Int,
    targetHeight: Int,
    duration: Long = 400,
    listener: Animator.AnimatorListener? = null,
    action: ((Float) -> Unit)? = null
): ValueAnimator? {
    var animator: ValueAnimator? = null
    post {
        val startHeight = height
        val evaluator = IntEvaluator()
        animator = ValueAnimator.ofInt(width, targetWidth).apply {
            addUpdateListener {
                setSize(
                    it.animatedValue as Int,
                    evaluator.evaluate(it.animatedFraction, startHeight, targetHeight)
                )
                action?.invoke((it.animatedFraction))
            }
            if (listener != null) addListener(listener)
            setDuration(duration)
            start()
        }
    }
    return animator
}

/**
 * 透明动画
 * @param duration 动画时长
 * @param alpha 透明度
 * @param delay 后续属性动画的延迟
 * @param animatorEnd 结束动画
 * @param animListener 动画监听器，会覆盖animatorEnd
 */
fun View.animAlpha(
    duration: Long = 600,
    alpha: Float = 0f,
    delay: Long = 0,
    animatorEnd: ((Animator?) -> Unit)? = null,
    animListener: Animator.AnimatorListener? = null
) {
    //this指代的是View这个接收者对象实例, 这里this也可以省略
    this.animate()
        .setDuration(duration)
        .setInterpolator(AccelerateDecelerateInterpolator())
        .setStartDelay(delay)
        .alpha(alpha)
        .setListener(
            animListener
                ?: object : Animator.AnimatorListener {
                    override fun onAnimationRepeat(animation: Animator) {
                    }

                    override fun onAnimationEnd(animation: Animator) {
                        animatorEnd?.invoke(animation)
                    }

                    override fun onAnimationCancel(animation: Animator) {
                    }

                    override fun onAnimationStart(animation: Animator) {

                    }
                }
        )
        .start()
}

/**
 * 设置View组件的显示和消失透明度动画，通过isVisible控制
 */
fun View.animAlphaVisible(
    isVisible: Boolean,
    duration: Long = 600,
    animatorEnd: ((Animator?) -> Unit)? = null
) {
    //扩展函数内部再调用扩展函数animAlpha
    animAlpha(duration, alpha = if (isVisible) 1f else 0f, animatorEnd = animatorEnd)
}

/**
 * 设置View的margin
 * @receiver View
 * @param left Int -1 则取原始值
 * @param top Int -1 则取原始值
 * @param right Int -1 则取原始值
 * @param bottom Int -1 则取原始值
 * @return View
 */
fun View.margin(left: Int = -1, top: Int = -1, right: Int = -1, bottom: Int = -1): View {
    val params = layoutParams ?: ViewGroup.MarginLayoutParams(
        ViewGroup.LayoutParams.WRAP_CONTENT,
        ViewGroup.LayoutParams.WRAP_CONTENT
    )
    if (params is ViewGroup.MarginLayoutParams) {
        var newLeft = left
        var newTop = top
        var newRight = right
        var newBottom = bottom
        if (params.leftMargin >= 0 && newLeft == -1) {
            newLeft = params.leftMargin
        }
        if (params.topMargin >= 0 && newTop == -1) {
            newTop = params.topMargin
        }
        if (params.rightMargin >= 0 && newRight == -1) {
            newRight = params.rightMargin
        }
        if (params.bottomMargin >= 0 && newBottom == -1) {
            newBottom = params.bottomMargin
        }
        params.setMargins(newLeft, newTop, newRight, newBottom)
    }
    this.layoutParams = params
    return this
}

/**
 * 设置View内容的gravity方式
 */
fun View.setContentGravity(gravity: Int): View {
    val params = layoutParams ?: ViewGroup.LayoutParams(
        ViewGroup.LayoutParams.WRAP_CONTENT,
        ViewGroup.LayoutParams.WRAP_CONTENT
    )
    if (params is LinearLayout.LayoutParams) {
        params.gravity = gravity
    }
    this.layoutParams = params
    return this
}

/**
 * 获取Activity
 */
fun View.getActivity(): Activity? {
    var context = context
    while (context is ContextWrapper) {
        if (context is Activity) {
            return context
        }
        context = context.baseContext
    }
    return null
}
/**
 *设置背景的替代颜色
 * @param colorResId 形如：R.color.color_2964FF
 */
fun View.setBackgroundTint(colorResId: Int) {
    this.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(context, colorResId))
}